#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/soc/cirrus/ep93xx.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>


static int link_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
{
    return 0;
}

static const struct snd_soc_ops tiny_link_ops = {
	.hw_params	= link_hw_params,
};


static struct snd_soc_dai_link_component tiny_link_codec_dlc;
static struct snd_soc_dai_link_component tiny_link_cpu_dlc;
static struct snd_soc_dai_link_component tiny_link_platform_dlc;


static struct snd_soc_dai_link tiny_link_dai = {
	.name		    = "tiny_link",
	.stream_name	= "DAI link",
	.dai_fmt	    = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBC_CFC,
	.ops		    = &tiny_link_ops,

	.cpus	            = &tiny_link_cpu_dlc,
	.codecs	            = &tiny_link_codec_dlc,
	.platforms	        = &tiny_link_platform_dlc,

	.num_cpus		    = 1,
	.num_codecs	        = 1,
	.num_platforms	    = 1,
};


static struct snd_soc_card tiny_card = {
	.name		= "tiny_card",
	.owner		= THIS_MODULE,
	.dai_link	= &tiny_link_dai,
	.num_links	= 1,
};


static int asoc_probe(struct platform_device *pdev)
{
	struct snd_soc_card *card = &tiny_card;
	struct device *dev = &pdev->dev;
	int ret;

	pr_info("link device name = %s\n", dev_name(dev));

	//platforms->name字符串必须和codecs->name的字符串相同
	//platforms->name和codecs->name这个字段的值必须是codec的platform device name, 可以在/sys/device/class中查看
	card->dev = &pdev->dev;
	card->dai_link->codecs->dai_name	= "tiny_codec";
	card->dai_link->codecs->name	    = "tiny_codec_dev.0";

	card->dai_link->cpus->dai_name	    = "tiny_cpu";
	// card->dai_link->cpus->name	        = "tiny_cpu";

	//card->dai_link->platforms->dai_name	= dev_name(dev);
	card->dai_link->platforms->name	    = "tiny_codec_dev.0";

	ret = snd_soc_register_card(card);
    if(ret) {
        pr_info("snd_soc_register_card failed: %d\n", ret);
        return -1;
    }

    return 0;
}


static void asoc_release(struct device * dev)
{

}

static struct platform_device tiny_link_device = {
    .name         = "tiny-card",
    .id       = -1,
    .dev = { 
    	.release = asoc_release, 
	},
};


static struct platform_driver tiny_link_driver = {
	.probe		= asoc_probe,
	.driver		= {
		.name	= "tiny-card",
	},
};


static int __init tiny_card_init(void)
{
	int ret  = platform_driver_register(&tiny_link_driver);
	if (ret < 0) {
        pr_info("platform_driver_register failed\n");
        return -1;
    }

    ret = platform_device_register(&tiny_link_device);
    if(ret) {
        pr_info("platform_device_register failed: %d\n", ret);
        return -1;
    }

    return 0;
}

static void __exit tiny_card_exit(void)
{
    /* 注销声卡 */
    snd_soc_unregister_card(&tiny_card);
	platform_device_unregister(&tiny_link_device);
}

module_init(tiny_card_init);
module_exit(tiny_card_exit);

MODULE_AUTHOR("1477153217@qq.com");
MODULE_DESCRIPTION("Custom DAI Link Driver");
MODULE_LICENSE("GPL");